<!--
 * @Author: weidewei
 * @Date: 2025-10-27 15:02:46
 * @LastEditors: weidewei
 * @LastEditTime: 2025-10-27 16:04:33
 * @Description: 
 * @FilePath: \2025-front-face\vue\复习vue2响应式原理.html
-->
<script>
  // 1.数据劫持
  // 2.依赖收集
  // 3.派发更新

  function isObject(obj) {
    return obj !== null && !Array.isArray(obj) && typeof obj === "object";
  }

  // 数据劫持
  function observer(obj) {
    if (!isObject(obj)) return;
    Object.keys(obj).forEach((key) => {
      let dep = new Dep();  
      let value = obj[key]; // 保存当前值，避免在getter中递归调用 [Exception: RangeError: Maximum call stack size exceeded at Object.get [as age]
      observer(value);
      if (isObject(value)) {
        observer(value);
      }
      Object.defineProperty(obj, key, {
        get() {
          console.log(`读取${key}的值为：${value}`);
          dep.depend();
          return value;
        },
        set(newValue) {
          // 如果新值是对象，递归监听
          observer(newValue);
          console.log(`设置${key}的值为：${newValue}`);
          dep.notify();
          value = newValue;
        },
      });
    });
  }

  let activeFn;

  // 依赖收集
  class Dep {
    constructor() {
      this.subsDeps = new Set();
    }

    depend() {
      this.subsDeps.add(activeFn);
    }

    notify() {
        this.subsDeps.forEach(fn=>fn());
    }
  }

  function autoRun(fn) {
    function updateWrapper() {
      activeFn = updateWrapper;
      fn();
      activeFn = null;
    }
    updateWrapper();
  }

  const state = {
    name: "张三",
    age: 20,
    province: {
      city: {
        name: "北京",
      },
    },
  };
  observer(state);
    autoRun(() => {
      console.log("依赖的副作用函数重新执行了~~", state.name);
    });

  state.name = "李四";
</script>
